package com.lagou.service.impl;

import com.lagou.entity.Order;
import com.lagou.entity.Stock;
import com.lagou.repository.OrderRepository;
import com.lagou.service.OrderService;
import com.lagou.service.StockService;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

/**
 * @author 13771
 * @date 2021/1/15 16:07
 * @description
 */
@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private StockService stockService;

    @Override
    public boolean saveOrUpdate(Order order) {
        orderRepository.save(order);
        return true;
    }

    @Override
    public Order findById(Integer id) {
        return orderRepository.findById(id).get();
    }

    @Override
    public boolean order(Integer stockId) {
        Order order = new Order();
        order.setStatus(0);
        order.setCreateTime(new Date());
        order.setStockId(stockId);

        //先从redis检查库存,如果量足够，则向rocketmq发送订单消息
        boolean flag = subtractStock(1,stockId);
        if (flag){
            rocketMQTemplate.convertAndSend("springboot-mq",order);
        }
        return flag;
    }

    @Override
    public String pay(Integer orderId) {
        String result = null;
        Order order = findById(orderId);
        if (order.getStatus() == 1){
            result = "已支付";
        }else if(order.getStatus() == 2) {
            result = "订单超时";
        }else {
            Boolean delete = redisTemplate.delete("order:" + orderId);
            order.setStatus(1);
            saveOrUpdate(order);
            result = "支付成功";
        }

        return result;
    }

    /**
     * Redis乐观锁实现秒杀
     * @param min
     * @return
     */
    public boolean subtractStock(Integer min,Integer stockId) {
        String key = "num";
        Integer num = 0;

        Object value = redisTemplate.opsForValue().get(key);
        if (value == null) {
            //如果没有命中redis的缓存，则从db中查出库存，并放入redis缓存中
            Stock stock = stockService.findById(stockId);
            num = stock.getNum();
            redisTemplate.opsForValue().set(key, String.valueOf(num));
        }else {
            num = Integer.valueOf(value.toString());
        }

        //先检查 库存是否充足
        if (num < min) {
            System.out.println("库存不足");
            return false;
        }

        SessionCallback<Boolean> sessionCallback = new SessionCallback<Boolean>() {
            @Override
            public <K, V> Boolean execute(RedisOperations<K, V> redisOperations) throws DataAccessException {
                redisOperations.watch((K) key);
                redisOperations.multi();
                redisTemplate.opsForValue().increment(key, -min.longValue());

                List<Object> exec = redisTemplate.exec();
                if(exec!=null && exec.size()>0){
                    return true;
                }
                return false;
            }
        };
        return redisTemplate.execute(sessionCallback);
    }
}
